package com.work.washer.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.work.washer.dto.MachineReservationReq;
import com.work.washer.mapper.MachineMapper;
import com.work.washer.model.Comment;
import com.work.washer.model.Machine;
import com.work.washer.model.UseRecord;
import com.work.washer.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author
 * @description 针对表【type】的数据库操作Service实现
 * @createDate 2024-02-20 10:07:14
 */
@Service
public class MachineService extends ServiceImpl<MachineMapper, Machine>
        implements IService<Machine> {

    @Autowired
    private UserService userService;
    @Autowired
    private UseRecordService useRecordService;

    @Autowired
    private CommentService commentService;


    /**
     * 保留
     *
     * @param req 需要
     * @return boolean
     */
    public boolean reservation(MachineReservationReq req) {
        LocalDateTime startDate = LocalDateTime.of(LocalDate.now(), LocalTime.parse(req.getStartTime(), DateTimeFormatter.ofPattern("HH:mm")));
        LocalDateTime endDate = LocalDateTime.of(LocalDate.now(), LocalTime.parse(req.getEndTime(), DateTimeFormatter.ofPattern("HH:mm")));
        Machine machine = this.getById(req.getMachineId());
        if (machine == null) {
            throw new RuntimeException("书籍不存在");
        }
        User user = userService.getById(req.getUserId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        if (startDate.isBefore(LocalDateTime.now()) || endDate.isBefore(LocalDateTime.now())) {
            throw new RuntimeException("预约时间需要大于当前时间");
        }
        if (startDate.isAfter(endDate)) {
            throw new RuntimeException("开始时间不能大于结束时间");
        }
        List<UseRecord> records = useRecordService.getByMachineId(req.getMachineId());
        if (records == null || records.isEmpty()) {
            //可以预约
            UseRecord record = new UseRecord();
            record.setStatus(1);
            record.setMachineId(req.getMachineId());
            record.setStartTime(Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()));
            record.setEndTime(Date.from(endDate.atZone(ZoneId.systemDefault()).toInstant()));
            record.setUserId(req.getUserId());
            record.setCreateTime(new Date());
            record.setStore(req.getStore());
            record.setType(req.getType());
            record.setClothesType(req.getClothesType());
            record.setWashType(req.getWashType());
            useRecordService.save(record);
            return true;
        }
        Date start = Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant());
        Date end = Date.from(endDate.atZone(ZoneId.systemDefault()).toInstant());
        records.forEach(e -> {
            if ((start.before(e.getEndTime()) && start.after(e.getStartTime())) ||
                    (end.compareTo(e.getEndTime()) <= 0 && end.compareTo(e.getStartTime()) >= 0)) {
                throw new RuntimeException("当前时段的设备已被预约");
            }
        });
        UseRecord record = new UseRecord();
        record.setStatus(1);
        record.setMachineId(req.getMachineId());
        record.setStartTime(Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()));
        record.setEndTime(Date.from(endDate.atZone(ZoneId.systemDefault()).toInstant()));
        record.setUserId(req.getUserId());
        record.setCreateTime(new Date());
        record.setStore(req.getStore());
        record.setType(req.getType());
        record.setClothesType(req.getClothesType());
        record.setWashType(req.getWashType());
        useRecordService.save(record);
        return true;
    }

    public boolean useBook(MachineReservationReq req) {
        Machine machine = this.getById(req.getMachineId());
        if (machine.getWorkState() == 3) {
            throw new RuntimeException("设备使用中");
        }
        List<UseRecord> records = useRecordService.getByMachineId(req.getMachineId());
        if (records != null && records.isEmpty()) {
            List<UseRecord> collect = records.stream().filter(e -> !e.getUserId().equals(req.getUserId())).collect(Collectors.toList());
            for (UseRecord e : collect) {
                if (e.getStartTime().getTime() < System.currentTimeMillis() && e.getEndTime().getTime() > System.currentTimeMillis()) {
                    throw new RuntimeException("设备已被预约");
                }
            }
        }
        UseRecord useRecord = useRecordService.getByUserIdAndMachineId(req.getUserId(), req.getMachineId());

        if (useRecord == null) {
            UseRecord record = new UseRecord();
            record.setStatus(2);
            record.setMachineId(req.getMachineId());
            record.setStartTime(new Date());
            record.setUserId(req.getUserId());
            record.setCreateTime(new Date());
            record.setStore(req.getStore());
            record.setType(req.getType());
            record.setClothesType(req.getClothesType());
            record.setWashType(req.getWashType());
            useRecordService.save(record);
        } else {
            useRecord.setStartTime(new Date());
            useRecord.setStatus(2);
            useRecordService.updateById(useRecord);
        }
        machine.setWorkState(3);
        this.updateById(machine);
        return true;
    }

    public boolean useRecord(Integer recordId, Integer userId) {
        UseRecord record = useRecordService.getById(recordId);
        Machine machine = this.getById(record.getMachineId());
        if (machine.getWorkState() == 3) {
            throw new RuntimeException("设备使用中");
        }
        record.setStatus(2);
        record.setStartTime(new Date());
        useRecordService.updateById(record);
        machine.setWorkState(3);
        this.updateById(machine);
        return true;
    }

    public boolean end(Integer recordId, Integer userId) {
        UseRecord record = useRecordService.getById(recordId);
        record.setStatus(3);
        record.setEndTime(new Date());
        useRecordService.updateById(record);
        Machine machine = this.getById(record.getMachineId());
        machine.setWorkState(1);
        this.updateById(machine);
        return true;
    }

    public List<UseRecord> listRecord(Integer userId, Integer status) {
        List<UseRecord> list = new ArrayList<>();
        if (status == 1) {
            list = useRecordService.lambdaQuery()
                    .eq(UseRecord::getUserId, userId)
                    .eq(UseRecord::getStatus, status)
                    .orderByDesc(UseRecord::getId).list();

        }
        if (status == 2) {
            list = useRecordService.lambdaQuery()
                    .eq(UseRecord::getUserId, userId)
                    .ne(UseRecord::getStatus, 1)
                    .orderByDesc(UseRecord::getId).list();
        }
        list.forEach(e -> {
            Machine machine = this.getById(e.getMachineId());
            e.setMachine(machine);
        });
        return list;
    }

    public boolean addComment(Integer machineId, Integer userId, String content) {
        Comment comment = new Comment();
        comment.setMachineId(machineId);
        comment.setUserId(userId);
        comment.setCreateDate(new Date());
        comment.setContent(content);
        commentService.save(comment);
        return true;
    }

    public void updateStatus() {
        Date start = Date.from(LocalDate.now().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
        List<Machine> machines = lambdaQuery().ne(Machine::getWorkState, 3).list();
        machines.forEach(e -> {
            e.setWorkState(1);
            this.updateById(e);
        });
        List<UseRecord> list = useRecordService.lambdaQuery()
                .eq(UseRecord::getStatus, 1)
                .le(UseRecord::getStartTime, start)
                .ge(UseRecord::getEndTime, start).list();
        if (list != null && !list.isEmpty()) {
            list.forEach(e -> {
                Machine machine = this.getById(e.getMachineId());
                machine.setWorkState(2);
                this.updateById(machine);
            });
        }
    }

    public List<Comment> getComment(Integer machineId) {
        return commentService.getByMachineId(machineId);
    }


    public Boolean refunds(Integer recordId) {
        UseRecord useRecord = useRecordService.getById(recordId);
        useRecord.setStatus(4);
        useRecordService.updateById(useRecord);
        Machine machine = this.getById(useRecord.getMachineId());
        machine.setWorkState(1);
        this.updateById(machine);
        return true;
    }

    public List<UseRecord> record(Integer machineId) {
        List<UseRecord> list = useRecordService.lambdaQuery()
                .eq(UseRecord::getStatus, 3)
                .eq(UseRecord::getMachineId, machineId)
                .orderByDesc(UseRecord::getId).list();

        list.forEach(e -> {
            Machine machine = this.getById(e.getMachineId());
            e.setMachine(machine);
        });
        return list;

    }
}





